// 套接字  实现断开重连；

#include <func.h>

int main(int argc, char *argv[])
{
  ARGS_CHECK(argc, 3);
  // 创建流；
  int sfd = socket(AF_INET, SOCK_STREAM, 0); // 创建一个流
  ERROR_CHECK(sfd, -1, "socket");
  // 创建一个结构体(ipv4类型的),并且初始化这个结构体

  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = inet_addr(argv[1]);
  addr.sin_port = htons(atoi(argv[2]));
  int optval = 1;
  int ret = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int)); // 不需要那个waittime
  ERROR_CHECK(ret, -1, "setsockopt");
  // 这是一个服务器所以需要bind(绑定ip锁定端口)listen(半连接 ,全连接) accept(会返回一个新的流)

  ret = bind(sfd, (struct sockaddr *)&addr, sizeof(addr));
  ERROR_CHECK(ret, -1, "bind");
  ret = listen(sfd, 10);
  ERROR_CHECK(ret, -1, "listen");
  // 需要创建一个新的套接字（流）
  //int netfd = accept(sfd, NULL, NULL);
  //ERROR_CHECK(netfd, -1, "netfd");

  char buf[4096] = {0};
  fd_set rdset; // 单纯的保存监听集合
  fd_set monitorSet;//使用一个单独的监听集合
// 加入监听 然后读写；
    FD_ZERO(&rdset);
    FD_ZERO(&monitorSet);
    FD_SET(sfd, &monitorSet);
    FD_SET(STDIN_FILENO, &monitorSet); 
    int netfd =-1;
  while (1)
  {
    memcpy(&rdset,&monitorSet,sizeof(fd_set));//
    int ret = select(20, &rdset, NULL, NULL, NULL);
    ERROR_CHECK(ret, -1, "select");
    if (FD_ISSET(sfd, &rdset))
    {
      netfd = accept(sfd,NULL,NULL);
      ERROR_CHECK(netfd,-1,"accept");
      FD_SET(netfd,&monitorSet);
      puts("new connect is accepted!\n");
      
    }
    if (FD_ISSET(STDIN_FILENO, &rdset))
    {
      // 写就绪；
      memset(buf, 0, sizeof(buf));
      int ret = read(STDIN_FILENO, buf, sizeof(buf));
      if (ret == 0)
      {
        printf("end\n");
        break;
      }
      send(netfd, buf, strlen(buf), 0);
  
    }
    
    if(FD_ISSET(netfd,&rdset))
    {
      memset(buf,0,sizeof(buf));
      ret = recv(netfd,buf,sizeof(buf),0);
      if(ret ==0)
      {
        puts("byebye");
        FD_CLR(netfd,&monitorSet);
        close(netfd);
        netfd=-1;
        continue;
      }
      puts(buf);
    }
  }
  close(sfd);
  
  return 0;
}